using System;
using System.Web.Routing;
using ManagedUIFlow.Infrastructure.Services.Helpers;
using ManagedUIFlow.Model;

namespace ManagedUIFlow.Infrastructure.Services
{
    public class DistinctSessionFlowViewService : IFlowViewService
    {
        private FlowService _flowService;
        public const string RedirectTicketKey = "PostRedirectGetServiceTicket";
        public const string RedirectUrlKey = "PostRedirectGetServiceUrl";

        public FlowService FlowService
        {
            get
            {
                return _flowService ?? FlowService.Current;
            }
            set { _flowService = value; }
        }

        public string Serialize(ManagedFlow flow, RequestContext requestContext)
        {
            requestContext.HttpContext.Session.Remove(requestContext.GetKey());
            var newKey = Guid.NewGuid().ToString();                           
            requestContext.HttpContext.Session.Add(newKey, flow);
            return newKey;
        }

        public ManagedFlow Deserialize(string key, RequestContext requestContext)
        {
            var flow = (ManagedFlow)requestContext.HttpContext.Session[key];
            if (flow != null)
            {
                var newNavigation = FlowService.GetNavigationFor(flow.Name, flow.CurrentNavigation,
                                                                 requestContext.GetState());
                flow.SetNavigation(newNavigation);
                return flow;
            }

            throw new FlowException(
                    "Either you have used browser back/refresh button or unable to restore the flow.");                
        }

        public void Remove(ManagedFlow flow, RequestContext requestContext)
        {
            requestContext.HttpContext.Session.Remove(flow.Key.ToString());
        }

        public void PostRedirectGet(string key, ManagedFlow flow, RequestContext context)
        {
            if (IsRedirectBack(context))
            {
                context.HttpContext.Session.Remove(RedirectTicketKey);        
                return;
            }
            context.HttpContext.Session.Add(RedirectTicketKey, flow);
            var redirectUrl = !string.IsNullOrEmpty(flow.RedirectUrl)
                                      ? flow.RedirectUrl
                                      : flow.Name;
            context.RouteData.Values["controller"] = key;
            context.HttpContext.Response.Redirect(UrlHelper.GenerateUrl(null, redirectUrl, null,
                                                                      new RouteValueDictionary(),
                                                                      RouteTable.Routes, context, false
                /* includeImplicitMvcValues */));
        }

        private static bool IsRedirectBack(RequestContext requestContext)
        {
            return requestContext.HttpContext.Session[RedirectTicketKey] != null;
        }
    }
}